package com.dzt.androidframework.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.dzt.androidframework.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by M02323 on 2017/11/20.
 * 自定义圆形仪表盘View，适合根据数值显示不同等级范围的场景
 * 转自：https://github.com/WangGanxin/CircleRangeView
 */

public class CircleRangeView extends View{
	private int mPadding;
	private int mRadius; // 画布边缘半径（去除padding后的半径）
	private int mStartAngle = 150; // 起始角度
	private int mSweepAngle = 240; // 绘制角度

	private int mSparkleWidth; // 指示标宽度
	private int mCalibrationWidth; // 刻度圆弧宽度
	private float mLength1; // 刻度顶部相对边缘的长度
	private float mCenterX, mCenterY; // 圆心坐标

	private Paint mPaint;
	private RectF mRectFProgressArc;
	private RectF mRectFCalibrationFArc;
	private Rect mRectText;

	private CharSequence[] rangeColorArray;

	private CharSequence[] rangeValueArray;
	private CharSequence[] rangeTextArray;
	private int borderColor = ContextCompat.getColor(getContext(), R.color.wdiget_circlerange_border_color);

	private int cursorColor = ContextCompat.getColor(getContext(), R.color.wdiget_circlerange_cursor_color);
	private int extraTextColor = ContextCompat.getColor(getContext(), R.color.widget_circlerange_extra_color);
	private int rangeTextSize = sp2px(34); //中间文本大小

	private int extraTextSize = sp2px(14); //附加信息文本大小
	private int borderSize = dp2px(5); //进度圆弧宽度

	private int mBackgroundColor;
	private int mSection = 0; // 等分份数
	private String currentValue;
	private List<String> extraList = new ArrayList<>();

	private boolean isAnimFinish = true;
	private float mAngleWhenAnim;

	public CircleRangeView(Context context) {
		this(context, null);
	}

	public CircleRangeView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public CircleRangeView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);

		TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleRangeView);

		rangeColorArray = typedArray.getTextArray(R.styleable.CircleRangeView_rangeColorArray);
		rangeValueArray = typedArray.getTextArray(R.styleable.CircleRangeView_rangeValueArray);
		rangeTextArray = typedArray.getTextArray(R.styleable.CircleRangeView_rangeTextArray);

		borderColor = typedArray.getColor(R.styleable.CircleRangeView_borderColor, borderColor);
		cursorColor = typedArray.getColor(R.styleable.CircleRangeView_cursorColor, cursorColor);
		extraTextColor = typedArray.getColor(R.styleable.CircleRangeView_extraTextColor, extraTextColor);

		rangeTextSize = typedArray.getDimensionPixelSize(R.styleable.CircleRangeView_rangeTextSize, rangeTextSize);
		extraTextSize = typedArray.getDimensionPixelSize(R.styleable.CircleRangeView_extraTextSize, extraTextSize);

		typedArray.recycle();

		if (rangeColorArray == null || rangeValueArray == null || rangeTextArray == null) {
			throw new IllegalArgumentException("CircleRangeView : rangeColorArray、 rangeValueArray、rangeTextArray  must be not null ");
		}
		if (rangeColorArray.length != rangeValueArray.length
				|| rangeColorArray.length != rangeTextArray.length
				|| rangeValueArray.length != rangeTextArray.length) {
			throw new IllegalArgumentException("arrays must be equal length");
		}

		this.mSection = rangeColorArray.length;

		mSparkleWidth = dp2px(15);
		mCalibrationWidth = dp2px(10);

		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		mPaint.setStrokeCap(Paint.Cap.ROUND);

		mRectFProgressArc = new RectF();
		mRectFCalibrationFArc = new RectF();
		mRectText = new Rect();

		mBackgroundColor = android.R.color.transparent;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		mPadding = Math.max(
				Math.max(getPaddingLeft(), getPaddingTop()),
				Math.max(getPaddingRight(), getPaddingBottom())
		);
		setPadding(mPadding, mPadding, mPadding, mPadding);

		mLength1 = mPadding + mSparkleWidth / 2f + dp2px(12);

		int width = resolveSize(dp2px(220), widthMeasureSpec);
		mRadius = (width - mPadding * 2) / 2;

		setMeasuredDimension(width, width - dp2px(30));

		mCenterX = mCenterY = getMeasuredWidth() / 2f;

		mRectFProgressArc.set(
				mPadding + mSparkleWidth / 2f,
				mPadding + mSparkleWidth / 2f,
				getMeasuredWidth() - mPadding - mSparkleWidth / 2f,
				getMeasuredWidth() - mPadding - mSparkleWidth / 2f
		);
		mRectFCalibrationFArc.set(
				mLength1 + mCalibrationWidth / 2f,
				mLength1 + mCalibrationWidth / 2f,
				getMeasuredWidth() - mLength1 - mCalibrationWidth / 2f,
				getMeasuredWidth() - mLength1 - mCalibrationWidth / 2f
		);

		mPaint.setTextSize(sp2px(10));
		mPaint.getTextBounds("0", 0, "0".length(), mRectText);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);


		canvas.drawColor(ContextCompat.getColor(getContext(), mBackgroundColor));

		/**
		 * 画圆弧背景
		 */
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(borderSize);
		mPaint.setAlpha(80);
		mPaint.setColor(borderColor);
		canvas.drawArc(mRectFProgressArc, mStartAngle + 1, mSweepAngle - 2, false, mPaint);

		mPaint.setAlpha(255);

		/**
		 * 画指示标
		 */
		if (isAnimFinish) {

			float[] point = getCoordinatePoint(mRadius - mSparkleWidth / 2f, mStartAngle + calculateAngleWithValue(currentValue));
			mPaint.setColor(cursorColor);
			mPaint.setStyle(Paint.Style.FILL);
			canvas.drawCircle(point[0], point[1], mSparkleWidth / 2f, mPaint);

		} else {

			float[] point = getCoordinatePoint(mRadius - mSparkleWidth / 2f, mAngleWhenAnim);
			mPaint.setColor(cursorColor);
			mPaint.setStyle(Paint.Style.FILL);
			canvas.drawCircle(point[0], point[1], mSparkleWidth / 2f, mPaint);
		}

		/**
		 * 画等级圆弧
		 */
		mPaint.setShader(null);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setColor(Color.BLACK);
		mPaint.setAlpha(255);
		mPaint.setStrokeCap(Paint.Cap.SQUARE);
		mPaint.setStrokeWidth(mCalibrationWidth);

		if (rangeColorArray != null) {
			for (int i = 0; i < rangeColorArray.length; i++) {
				mPaint.setColor(Color.parseColor(rangeColorArray[i].toString()));
				float mSpaces = mSweepAngle / mSection;
				if (i == 0) {
					canvas.drawArc(mRectFCalibrationFArc, mStartAngle + 3, mSpaces, false, mPaint);
				} else if (i == rangeColorArray.length - 1) {
					canvas.drawArc(mRectFCalibrationFArc, mStartAngle + (mSpaces * i), mSpaces, false, mPaint);
				} else {
					canvas.drawArc(mRectFCalibrationFArc, mStartAngle + (mSpaces * i) + 3, mSpaces, false, mPaint);
				}
			}
		}

		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setShader(null);
		mPaint.setAlpha(255);

		/**
		 * 画等级对应值的文本（居中显示）
		 */
		if (rangeColorArray != null && rangeValueArray != null && rangeTextArray != null) {

			if (!TextUtils.isEmpty(currentValue)) {
				int pos = 0;

				for (int i = 0; i < rangeValueArray.length; i++) {
					if (rangeValueArray[i].equals(currentValue)) {
						pos = i;
						break;
					}
				}

				mPaint.setColor(Color.parseColor(rangeColorArray[pos].toString()));
				mPaint.setTextAlign(Paint.Align.CENTER);

				String txt=rangeTextArray[pos].toString();

				if (txt.length() <= 4) {
					mPaint.setTextSize(rangeTextSize);
					canvas.drawText(txt, mCenterX, mCenterY + dp2px(10), mPaint);
				} else {
					mPaint.setTextSize(rangeTextSize - 10);
					String top = txt.substring(0, 4);
					String bottom = txt.substring(4, txt.length());

					canvas.drawText(top, mCenterX, mCenterY, mPaint);
					canvas.drawText(bottom, mCenterX, mCenterY + dp2px(30), mPaint);
				}
			}
		}

		/**
		 * 画附加信息
		 */
		if (extraList != null && extraList.size() > 0) {
			mPaint.setAlpha(160);
			mPaint.setColor(extraTextColor);
			mPaint.setTextSize(extraTextSize);
			for (int i = 0; i < extraList.size(); i++) {
				canvas.drawText(extraList.get(i), mCenterX, mCenterY + dp2px(50) + i * dp2px(20), mPaint);
			}
		}

	}

	private int dp2px(int dp) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
				Resources.getSystem().getDisplayMetrics());
	}

	private int sp2px(int sp) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
				Resources.getSystem().getDisplayMetrics());
	}

	/**
	 * 根据角度和半径进行三角函数计算坐标
	 * @param radius
	 * @param angle
	 * @return
	 */
	private float[] getCoordinatePoint(float radius, float angle) {
		float[] point = new float[2];

		double arcAngle = Math.toRadians(angle); //将角度转换为弧度
		if (angle < 90) {
			point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
			point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
		} else if (angle == 90) {
			point[0] = mCenterX;
			point[1] = mCenterY + radius;
		} else if (angle > 90 && angle < 180) {
			arcAngle = Math.PI * (180 - angle) / 180.0;
			point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
			point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
		} else if (angle == 180) {
			point[0] = mCenterX - radius;
			point[1] = mCenterY;
		} else if (angle > 180 && angle < 270) {
			arcAngle = Math.PI * (angle - 180) / 180.0;
			point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
			point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
		} else if (angle == 270) {
			point[0] = mCenterX;
			point[1] = mCenterY - radius;
		} else {
			arcAngle = Math.PI * (360 - angle) / 180.0;
			point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
			point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
		}

		return point;
	}

	/**
	 * 根据起始角度计算对应值应显示的角度大小
	 */
	private float calculateAngleWithValue(String level) {

		int pos = -1;

		for (int j = 0; j < rangeValueArray.length; j++) {
			if (rangeValueArray[j].equals(level)) {
				pos = j;
				break;
			}
		}

		float degreePerSection = 1f * mSweepAngle / mSection;

		if (pos == -1) {
			return 0;
		} else if (pos == 0) {
			return degreePerSection / 2;
		} else {
			return pos * degreePerSection + degreePerSection / 2;
		}
	}

	/**
	 * 设置值并播放动画
	 *
	 * @param value 值
	 */
	public void setValueWithAnim(String value) {
		setValueWithAnim(value,null);
	}

	/**
	 * 设置值并播放动画
	 *
	 * @param value  值
	 * @param extras 底部附加信息
	 */
	public void setValueWithAnim(String value, List<String> extras) {
		if (!isAnimFinish) {
			return;
		}

		this.currentValue = value;
		this.extraList=extras;

		// 计算最终值对应的角度，以扫过的角度的线性变化来播放动画
		float degree = calculateAngleWithValue(value);

		ValueAnimator degreeValueAnimator = ValueAnimator.ofFloat(mStartAngle, mStartAngle + degree);
		degreeValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				mAngleWhenAnim = (float) animation.getAnimatedValue();
				postInvalidate();
			}
		});

		long delay = 1500;

		AnimatorSet animatorSet = new AnimatorSet();
		animatorSet
				.setDuration(delay)
				.playTogether(degreeValueAnimator);
		animatorSet.addListener(new AnimatorListenerAdapter() {
			@Override
			public void onAnimationStart(Animator animation) {
				super.onAnimationStart(animation);
				isAnimFinish = false;
			}

			@Override
			public void onAnimationEnd(Animator animation) {
				super.onAnimationEnd(animation);
				isAnimFinish = true;
			}

			@Override
			public void onAnimationCancel(Animator animation) {
				super.onAnimationCancel(animation);
				isAnimFinish = true;
			}
		});
		animatorSet.start();
	}
}
